#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAX_E = 2 * 1000;
const int MAX_V = 100;

struct node { int v, next, w; } E[MAX_E];

int G[MAX_V];
int col[MAX_V], visited[MAX_V], low[MAX_V], stk[MAX_V];
int cnt, ls, scc;
bool inused[MAX_V];
int N;

void add_edge(int i, int j, int w=1) {
	E[cnt].v = j;
	E[cnt].next = G[i];
	E[cnt].w = w;
	G[i] = cnt++;
	
	//if (w > 0) add_edge(j, i, -w);
}

void tarjan(int i) {
	int v;
	visited[i] = low[i] = cnt++;
	inused[i] = 1;
	stk[ls++] = i;
	for (int j=G[i]; j!=-1; j=E[j].next) {
		v = E[j].v;
		if (visited[v] < 0) {
			tarjan(v);
			low[i] = min(low[i], low[v]);
		}
		else if (inused[v])
			low[i] = min(low[i], visited[v]);
	}

	if (visited[i] != low[i]) return;
	do {
		v = stk[--ls];
		inused[v] = 0;
		col[v] = scc;
	} while (v != i);
	++scc;
}

void test() {
	N = 4;
	add_edge(0, 1);
	add_edge(1, 2);
	add_edge(1, 3);
	add_edge(3, 0);
}

int main() {
	memset(G, -1, sizeof(G)); cnt = 0;
	test();

	memset(inused, 0, sizeof(inused));
	memset(visited, -1, sizeof(visited));
	ls = scc = 0;
	for (int i=0; i<N; ++i) if (visited[i]<0) tarjan(i);

	for (int i=0; i<N; ++i) printf("col[%d] = %d\n", i, col[i]);
	return 0;
}	
